<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery.min.js"></script>
    <script src="crypto-js.min.js"></script>
    <script src="jsencrypt.min.js"></script>
    <script src="config.js"></script>
</head>
<body style="height: 100%">

<div style="display: flex;height: 65vh;overflow: auto">

    <div style="width: 80%">

        <div>token数据</div>
        <textarea id="token" cols="30" rows="5" style="width: 100%" >f1AvR4vU2Cw7zLbWMv++wJKdCReS48xx35XeVuZJ2+dwCQ4f39xgjTwwBCimj/DOhTXc0UeMDof3V02AgoXUPGdWC1OWUp9l2Bmyg5QJpcVPmWFwxij33mBLJzYTzq0OntWaXxLmD2x3kxNY2X8fJ6d5xJhK2ly1Yc44sHjaZcg=</textarea>
        <div>解析数据:</div>
        <textarea id="setToken" cols="30" rows="5" style="width: 100%" ></textarea>

        <div>data数据</div>
        <textarea id="data" cols="30" rows="5" style="width: 100%" >2b505558314938423346505250574864795349734e43745150535464664238534d5a695665715133674b78794f45564854454e4d5a41576c386449347958344675384b6a6d3871476c79363630374e685532413233766a416a7a785972316a6f487a554f536f566c582b41316c546e576b327648646645495962476e76595075</textarea>
        <div>解析数据:</div>
        <textarea id="setData" cols="30" rows="5" style="width: 100%" ></textarea>

    </div>

    <div style="font-size: 18px;padding: 10.5% 0 0 5%">
        <input id="button-jie" style="width: 150px;margin: 20px 0" type="button" value="解密"/>
        <input id="button-jia" style="width: 150px" type="button" value="加密"/>
        <input id="button-clear" style="width: 150px" type="button" value="清空"/>
    </div>

</div>

<div style="display: flex;">

    <div style="width: 100%">
        <div>客户端公钥</div>
        <textarea id="clientPublicKey" cols="30" rows="10" style="width: 100%" > {$clientPublicKey}</textarea>
    </div>

    <div style="width: 100%">
        <div>客户端私钥</div>
        <textarea id="clientPrivateKey" cols="30" rows="10" style="width: 100%" > {$clientPrivateKey}</textarea>
    </div>

</div>


<div style="display: flex;">

    <div style="width: 100%">
        <div>服务端公钥</div>
        <textarea id="servicePublicKey" cols="30" rows="10" style="width: 100%" > {$servicePublicKey}</textarea>
    </div>


    <div style="width: 100%">
        <div>服务端私钥</div>
        <textarea id="servicePrivateKey" cols="30" rows="10" style="width: 100%" > {$servicePrivateKey}</textarea>
    </div>

</div>

</body>

<script>


    $('#clientPublicKey').val(clientPublicKey)
    $('#clientPrivateKey').val(clientPrivateKey)
    $('#servicePublicKey').val(servicePublicKey)
    $('#servicePrivateKey').val(servicePrivateKey)


    $('#button-clear').click(function () {
        $('#token').val('')
        $('#setToken').val('')
        $('#data').val('')
        $('#setData').val('')
    })


    /**
     * 加密数据
     */

    $('#button-jia').click(function () {

        let token =  $('#token').val()

        token = eval('(' +token+ ')')

        let aesKey = '1234567890abcdef' //必须16位字符串，要不然解析不出来

        token.aesKey = aesKey

        token = JSON.stringify(token)

        //加密
        let crypt = new JSEncrypt()

            crypt.setKey(servicePublicKey)

        let enc = crypt.encrypt(token)

        //转16进制
        token = strToUtf8Bytes(enc)


        $('#setToken').val(token)


        let data =  $('#data').val()

        let key = CryptoJS.enc.Utf8.parse(aesKey)

        let encryptedObj = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(data), key,
            {
                mode:CryptoJS.mode.ECB,
                padding:CryptoJS.pad.Pkcs7,
            },
        )

        let base64 = encryptedObj.toString()

       let encryptStr =   strToUtf8Bytes(base64.toString())

        $('#setData').val(encryptStr)


        $.ajax({
            url: 'http://jr-help:1000/example/TestRsa.php',
            type: 'POST',
            headers: {
                'client': 'web',
                'token':token,
            },
            data: encryptStr,

            success: function(response) {

                response = hexToStr(response,'utf-8')

                //解密
                let crypt = new JSEncrypt()
                crypt.setKey(clientPrivateKey)
                let dec = crypt.decrypt(response)
                dec = JSON.parse(atob(dec))
                console.log(dec)

            },
            error: function(xhr, status, error) {
                // 请求失败时的回调函数
            }
        });

    })



    /**
     * 解密数据
     */

    $('#button-jie').click(function () {

       let token =  $('#token').val()

        token = hexToStr(token,'utf-8')

       let data =  $('#data').val()

        //解密
        let crypt = new JSEncrypt()
            crypt.setKey(clientPrivateKey)
        let dec = crypt.decrypt(token)


        if (dec){

            dec = JSON.parse(atob(dec))

            $('#setToken').val(JSON.stringify(dec))

            let aesKey = dec.aesKey

            let key = CryptoJS.enc.Utf8.parse(aesKey)

            let decrypt = CryptoJS.AES.decrypt(hexToStr(data,'utf-8'), key,
                {
                    mode:CryptoJS.mode.ECB,
                    padding:CryptoJS.pad.Pkcs7,
                },
            )

            let decrypts =  CryptoJS.enc.Utf8.stringify(decrypt).toString()

            var jsonObj = JSON.stringify(JSON.parse(JSON.parse(decrypts)));

            if (jsonObj){
                $('#setData').val(jsonObj)
            }
        }

    })






    /**
     * 16进制转字符串
     * @param hex
     * @param encoding
     * @returns {string}
     */

    function hexToStr(hex,encoding) {
        var trimedStr = hex.trim();
        var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
        var len = rawStr.length;
        if (len % 2 !== 0) {
            alert("Illegal Format ASCII Code!");
            return "";
        }
        var curCharCode;
        var resultStr = [];
        for (var i = 0; i < len; i = i + 2) {
            curCharCode = parseInt(rawStr.substr(i, 2), 16);
            resultStr.push(curCharCode);
        }
        // encoding为空时默认为utf-8
        var bytesView = new Uint8Array(resultStr);
        var str = new TextDecoder(encoding).decode(bytesView);
        return str;
    }


    /**
     * 字符串转十六进制
     * @param str
     * @returns {string}
     */
    function strToUtf8Bytes(str) {
        const utf8 = [];
        for (let ii = 0; ii < str.length; ii++) {
            let charCode = str.charCodeAt(ii);
            if (charCode < 0x80) utf8.push(charCode);
            else if (charCode < 0x800) {
                utf8.push(0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f));
            } else if (charCode < 0xd800 || charCode >= 0xe000) {
                utf8.push(0xe0 | (charCode >> 12), 0x80 | ((charCode >> 6) & 0x3f), 0x80 | (charCode & 0x3f));
            } else {
                ii++;
                charCode = 0x10000 + (((charCode & 0x3ff) << 10) | (str.charCodeAt(ii) & 0x3ff));
                utf8.push(
                    0xf0 | (charCode >> 18),
                    0x80 | ((charCode >> 12) & 0x3f),
                    0x80 | ((charCode >> 6) & 0x3f),
                    0x80 | (charCode & 0x3f),
                );
            }
        }
        //兼容汉字，ASCII码表最大的值为127，大于127的值为特殊字符
        for(let jj=0;jj<utf8.length;jj++){
            var code = utf8[jj];
            if(code>127){
                utf8[jj] = code - 256;
            }
        }
        var hexCharCode = [];
        var chars = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"];
        for(var i = 0; i < utf8.length; i++) {
            var bit = (utf8[i] & 0x0f0) >> 4;
            hexCharCode.push(chars[bit]);
            var bit = utf8[i] & 0x0f;
            hexCharCode.push(chars[bit]);
        }
        return hexCharCode.join("");
    }

</script>

</html>
